package com.fitso.model.calculator;

import org.springframework.util.Assert;

import com.fitso.model.bean.Body;
import com.fitso.model.bean.Body.Sex;
import com.fitso.model.bean.measure.energy.Calorie;
import com.fitso.model.bean.measure.energy.Energy;
import com.fitso.model.bean.measure.length.CentiMeter;
import com.fitso.model.bean.measure.mass.KiloGram;
import com.fitso.model.bean.measure.mass.Mass;
import com.fitso.model.calculator.bmi.StandardBodyMassIndexCalculator;
import com.fitso.model.calculator.idealweight.BrocaIdealWeightCalculator;

/**
 * Convenience class that consolidates several body calculators
 * 
 * @author timothystorm
 */
public class ConsolidatedBodyCalculator implements BodyCalculator {
	private BodyMassIndexCalculator _bmi = new StandardBodyMassIndexCalculator();

	public void setBodyMassIndexCalculator(BodyMassIndexCalculator bmi) {
		_bmi = bmi;
	}

	public Double calculateBodyMassIndex(Body body) {
		return _bmi.calculate(body);
	}

	private IdealWeightCalculator _idealWeight = new BrocaIdealWeightCalculator();

	public void setIdealWeightCalculator(IdealWeightCalculator idealWeight) {
		_idealWeight = idealWeight;
	}

	public Mass calculateIdealWeight(Body body) {
		return _idealWeight.calculate(body);
	}

	public Energy calculateBasalMetabolicRate(Body body) {
		Assert.notNull(body, "body is required");

		KiloGram weight = new KiloGram(body.getWeight());
		CentiMeter height = new CentiMeter(body.getHeight());

		if (body.getSex() == Sex.MALE) {
			return new Calorie(weight.multiply(13.7).add(height.multiply(5)).subtract(6.8 * body.getAge()).add(66).getValue());
		} else if (body.getSex() == Sex.FEMALE) {
			return new Calorie(weight.multiply(9.6).add(height.multiply(1.8)).subtract(4.7 * body.getAge()).add(655).getValue());
		}
		return new Calorie(0.0);
	}

	public Energy calculateTotalDailyEnergyNeeds(Body body) {
		// TODO: Refactor out the switch, its a silly construct.
		Assert.notNull(body, "body is required");

		double multiplier = 1;
		switch (body.getActivityLevel()) {
		case SEDENTARY:
			multiplier += .2;
			break;
		case LIGHT:
			multiplier += .375;
			break;
		case MODERATE:
			multiplier += .55;
			break;
		case VERY:
			multiplier += .725;
			break;
		case EXTREME:
			multiplier += .9;
			break;
		}
		return new Calorie(calculateBasalMetabolicRate(body).multiply(multiplier));
	}
}
